/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package submarines;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import submarines.notices.*;
import javax.xml.bind.*;
import SubmarinesBindings.*;
import submarines.ui.Ui;
/**
 *
 * @author sshiran
 */
public class EaPlayer extends Player{
      public String[] result = null;
      
    public EaPlayer(String userName, int userScore)
    {
        super(userName, userScore);//call player constructor
        //this.fillBoard(); //fill user game board
        setType(Config.COMPUTER_PLAYER);
    }

    public EaPlayer()
    {
        super("", 0);//call player constructor
        setType(Config.COMPUTER_PLAYER);
    }
    
    public EaPlayer(String userName)
    {
        super(userName, 0);//call player constructor
        setType(Config.COMPUTER_PLAYER);
    }
    
    public EaPlayer(String name, List<SubmarinesBindings.Boat> xmlBoats, SubmarinesBindings.Board b) throws JAXBException { //constructor for XML import
        super(name, xmlBoats, b); //call player constructor
        setType(Config.COMPUTER_PLAYER);
    }
   

   @Override
    public void fillBoard()
    {
        int row;
        int col;
        int toSub;
         boolean success;
        int i, j;

        Random r = new Random();

        for (i = Config.SUBMARINES.length; i >= 1; i--) { //get all ships according to size
            j = Config.SUBMARINES[i-1]; //get number of ships from i size
            while (j > 0) {
                int direction = r.nextInt(2) +1; //get random direction to put ship
                
                if (direction == 1)
                {
                    row = r.nextInt(Config.BOARD_SIZE - 1); //when direction is horizontal the row can be any row in the board
                    toSub = Config.BOARD_SIZE - i; //when direction is horizontal the column is limited to board size minus ship size
                    col = r.nextInt(toSub);
                    success = myBoard.insertShip(row, col, i, direction);  //create ship according to details
                }
                else
                {
                    toSub = Config.BOARD_SIZE - i; 
                    row = r.nextInt(toSub);  //when direction is vertical the row is limited to board size minus ship size
                    col = r.nextInt(Config.BOARD_SIZE - 1);  //when direction is vertical the column can be any column in the board
                    success = myBoard.insertShip(row, col, i, direction);//create ship according to details
                }
               
                if (success) { //if success continue to next ship else try again
                    j--; 
                }
            }
        }
    }
    
    @Override
    public void notifyPlayerGotHit(Notice currNotice) {
        super.notifyPlayerGotHit(currNotice); //notify this player that another player got hit
    }
    
    @Override
    public void notifyPlayerSubmarineSunk(Notice currNotice) {
        super.notifyPlayerSubmarineSunk(currNotice);//notify this player that another player submatine sunk 
    }
    
    @Override
    public void notifyPlayerQuit(Notice currNotice) {
        super.notifyPlayerQuit(currNotice);//notify this player that another player quit 
    }
    
    @Override
    public void notifyPlayerGotLucky(Notice currNotice) {
        super.notifyPlayerGotLucky(currNotice);//notify this player that another player got luck and his submarined didn't got hit 
    }
    

    @Override
    public boolean playTurn() {
        boolean played;
        Player target;
        Random r = new Random();
        int enemies, eIndex, row, col, j;
        int hitResult;
        int[] coords = new int[2];
        enemyBoard eBoard = null;
        String[] result = null;
        
        readNotices(); //read all notices from other players to see the changes on their boards
        enemies = Main.pManager.numPlayersLeft(); //get all players
        eIndex = r.nextInt(enemies - 1); //minus the player itself
        played = false;
        LinkedList<String> names = new LinkedList<String>();
        for (int i = 0; i < Main.pManager.numPlayersLeft(); i++) {
            Player tmp = Main.pManager.getNextPlayer(); 
            if (!tmp.getName().equals(getName())) { //create a list of enemys players
                names.add(tmp.getName());
            }
        }
        
        target = Main.pManager.getPlayerByName(names.get(eIndex)); 
        for (j = 0; j < competitorBoard.size(); j++) {
            eBoard = competitorBoard.get(j);
            if (eBoard.belongsTo(target))
                break;
        }
        
        while (!played) { //if player didn't played yet
            coords = getNextTargetedCoords(eBoard); //get computer coordinates
            row = coords[0];
            col = coords[1];
            hitResult = target.getTorpedo(row, col);  //check if player hit in the selected dots
            if (hitResult >= 0) { 
                    //mark hit on the target board

                markOnBoard(Config.HIT_SQUARE_SIGN, target.getName(), row, col); //mark hit on target board
                NoticePlayerGotHit n = new NoticePlayerGotHit(target, Notice.NoticeType.PLAYER_GOT_HIT, row, col);//create a new notice to send to all other users
                Main.nManager.spreadTheWord(this, target, n);//tell all other players that player got hit
                
                if (hitResult > 0) { //if submrine sunk
                    NoticePlayerSubmarineSunk sunk = new NoticePlayerSubmarineSunk(target, Notice.NoticeType.PLAYER_SUBMARINE_SUNK, hitResult); //create a new notice to send to all other users
                    Main.nManager.spreadTheWord(this, target, sunk);//tell all other players that player submarine sunk
                }
                
                if (target.isDead()) { //if there is no more submarines to the player
                    NoticePlayerQuit q = new NoticePlayerQuit(target, Notice.NoticeType.PLAYER_QUIT); //create a notice that player quited
                    Main.pManager.playerQuit(target); //remove player from game
                    Main.nManager.spreadTheWord(this, this, q); //tell all other players that player quited
                    if (Main.pManager.numPlayersLeft() == 1) { //if only one player left in game don't give current player another turn despite his hit
                        played = true;
                    }
                }
                setTurnStatus(getName(), row, col);
                Main.userInterface.printComputerMove(getName(), eBoard, row, col); //pring computer moves in his turn
            } else {
                markOnBoard(Config.MISSED_SQUARE_SIGN, target.getName(), row, col); //if player didn't hit a submarine mark as missed
                played = true;
                setTurnStatus(getName(), row, col);
                Main.userInterface.printComputerMove(getName(), eBoard, row, col); //pring computer moves
                NoticePlayerGotLucky n = new NoticePlayerGotLucky(target, Notice.NoticeType.PLAYER_GOT_LUCKY, row, col); //create a notice that player was not hited
                Main.nManager.spreadTheWord(this, target, n); //send all other users the notice
            }
        }
        return false;
    }
    
    public boolean playTurn(PlayerManager pManager, NotficationManager nManager) { //for web
        boolean played;
        Player target;
        Random r = new Random();
        int enemies, eIndex, row, col, j;
        int hitResult;
        int[] coords = new int[2];
        enemyBoard eBoard = null;
        String[] result = null;
        
        readNotices(); //read all notices from other players to see the changes on their boards
        enemies = pManager.numPlayersLeft(); //get all players
        eIndex = r.nextInt(enemies - 1); //minus the player itself
        played = false;
        LinkedList<String> names = new LinkedList<String>();
        for (int i = 0; i < pManager.numPlayersLeft(); i++) {
            Player tmp = pManager.getNextPlayer(); 
            if (!tmp.getName().equals(getName())) { //create a list of enemys players
                names.add(tmp.getName());
            }
        }
        
        target = pManager.getPlayerByName(names.get(eIndex)); 
        for (j = 0; j < competitorBoard.size(); j++) {
            eBoard = competitorBoard.get(j);
            if (eBoard.belongsTo(target))
                break;
        }
        
        while (!played) { //if player didn't played yet
            coords = getNextTargetedCoords(eBoard); //get computer coordinates
            row = coords[0];
            col = coords[1];
            hitResult = target.getTorpedo(row, col);  //check if player hit in the selected dots
            if (hitResult >= 0) { 
                    //mark hit on the target board

                markOnBoard(pManager, Config.HIT_SQUARE_SIGN, target.getName(), row, col); //mark hit on target board
                NoticePlayerGotHit n = new NoticePlayerGotHit(target, Notice.NoticeType.PLAYER_GOT_HIT, row, col);//create a new notice to send to all other users
                nManager.spreadTheWord(this, target, n);//tell all other players that player got hit
                
                if (hitResult > 0) { //if submrine sunk
                    NoticePlayerSubmarineSunk sunk = new NoticePlayerSubmarineSunk(target, Notice.NoticeType.PLAYER_SUBMARINE_SUNK, hitResult); //create a new notice to send to all other users
                    nManager.spreadTheWord(this, target, sunk);//tell all other players that player submarine sunk
                }
                
                if (target.isDead()) { //if there is no more submarines to the player
                    NoticePlayerQuit q = new NoticePlayerQuit(target, Notice.NoticeType.PLAYER_QUIT); //create a notice that player quited
                    pManager.playerQuit(target); //remove player from game
                    nManager.spreadTheWord(this, this, q); //tell all other players that player quited
                    if (pManager.numPlayersLeft() == 1) { //if only one player left in game don't give current player another turn despite his hit
                        played = true;
                    }
                }
                setTurnStatus(getName(), row, col);
                //Main.userInterface.printComputerMove(getName(), eBoard, row, col); //pring computer moves in his turn
            } else {
                markOnBoard(pManager, Config.MISSED_SQUARE_SIGN, target.getName(), row, col); //if player didn't hit a submarine mark as missed
                played = true;
                setTurnStatus(getName(), row, col);
                //Main.userInterface.printComputerMove(getName(), eBoard, row, col); //pring computer moves
                NoticePlayerGotLucky n = new NoticePlayerGotLucky(target, Notice.NoticeType.PLAYER_GOT_LUCKY, row, col); //create a notice that player was not hited
                nManager.spreadTheWord(this, target, n); //send all other users the notice
            }
        }
        return false;
    }
    
    public Config.turnStatus playSingleTurn (PlayerManager pManager, NotficationManager nManager) {
        Config.turnStatus ret;
        boolean played;
        Player target;
        Random r = new Random();
        int enemies, eIndex, row, col, j;
        int hitResult;
        int[] coords = new int[2];
        enemyBoard eBoard = null;
        String[] result = null;
        
        readNotices(); //read all notices from other players to see the changes on their boards
        enemies = pManager.numPlayersLeft(); //get all players
        eIndex = r.nextInt(enemies - 1); //minus the player itself
        played = false;
        LinkedList<String> names = new LinkedList<String>();
        for (int i = 0; i < pManager.numPlayersLeft(); i++) {
            Player tmp = pManager.getNextPlayer(); 
            if (!tmp.getName().equals(getName())) { //create a list of enemys players
                names.add(tmp.getName());
            }
        }
        
        target = pManager.getPlayerByName(names.get(eIndex)); 
        for (j = 0; j < competitorBoard.size(); j++) {
            eBoard = competitorBoard.get(j);
            if (eBoard.belongsTo(target))
                break;
        }
        
            coords = getNextTargetedCoords(eBoard); //get computer coordinates
            row = coords[0];
            col = coords[1];
            hitResult = target.getTorpedo(row, col);  //check if player hit in the selected dots
            if (hitResult >= 0) { 
                    //mark hit on the target board

                markOnBoard(pManager, Config.HIT_SQUARE_SIGN, target.getName(), row, col); //mark hit on target board
                NoticePlayerGotHit n = new NoticePlayerGotHit(target, Notice.NoticeType.PLAYER_GOT_HIT, row, col);//create a new notice to send to all other users
                nManager.spreadTheWord(this, target, n);//tell all other players that player got hit
                ret = Config.turnStatus.HIT;
                
                if (hitResult > 0) { //if submrine sunk
                    NoticePlayerSubmarineSunk sunk = new NoticePlayerSubmarineSunk(target, Notice.NoticeType.PLAYER_SUBMARINE_SUNK, hitResult); //create a new notice to send to all other users
                    nManager.spreadTheWord(this, target, sunk);//tell all other players that player submarine sunk
                    ret = Config.turnStatus.SHIP_SANK;
                }
                
                if (target.isDead()) { //if there is no more submarines to the player
                    NoticePlayerQuit q = new NoticePlayerQuit(target, Notice.NoticeType.PLAYER_QUIT); //create a notice that player quited
                    pManager.playerQuit(target); //remove player from game
                    nManager.spreadTheWord(this, this, q); //tell all other players that player quited
                    ret = Config.turnStatus.PLAYER_LOST;
                }
                setTurnStatus(target.getName(), row, col);
                
                //Main.userInterface.printComputerMove(getName(), eBoard, row, col); //pring computer moves in his turn
            } else {
                markOnBoard(pManager, Config.MISSED_SQUARE_SIGN, target.getName(), row, col); //if player didn't hit a submarine mark as missed
                played = true;
                setTurnStatus(target.getName(), row, col);
                //Main.userInterface.printComputerMove(getName(), eBoard, row, col); //pring computer moves
                NoticePlayerGotLucky n = new NoticePlayerGotLucky(target, Notice.NoticeType.PLAYER_GOT_LUCKY, row, col); //create a notice that player was not hited
                ret = Config.turnStatus.MISSED;
                pManager.playersTurn();               
                //Main.nManager.spreadTheWord(this, target, n); //send all other users the notice
            }
        
        return ret;
    }
    
    void setTurnStatus(String name, int row, int col)
    {
        result = new String[3];
        result[0] = name;
        result[1] = row + "";
        result[2] = col + "";
    }
    
    public String[] getEaMoves()
    {
        return result;
    }
    
    int[] getNextTargetedCoords(enemyBoard e) {
        int [] coords = new int[2];
        Random r = new Random();
        coords[0] = r.nextInt(Config.BOARD_SIZE);
        coords[1] = r.nextInt(Config.BOARD_SIZE);
        
        while (!((e.canBeTargeted(coords[0], coords[1])) && (!e.isMarked(coords[0], coords[1])))) {//check that selected coords is not taken
            coords[0] = r.nextInt(Config.BOARD_SIZE);
            coords[1] = r.nextInt(Config.BOARD_SIZE);
        }
        
        return coords;
    }
}
 
